package com.jy.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.OrderPayChannel;
import com.jy.api.payReq.*;
import com.jy.api.payRes.*;
import com.jy.api.payUtil.RSA256Utils;
import com.jy.api.payservice.CommonService;
import com.jy.api.payservice.TransExecuteService;
import com.jy.api.service.StorePayService;
import com.jy.api.util.AliyunMNSSend;
import com.jy.api.util.MyDateUtils;
import com.jy.api.util.RedisSyncLocker;
import com.jy.api.util.UuidUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class JLServiceImpl implements StorePayService {
    @Autowired
    private AliyunMNSSend aliyunMNSSend;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private PaymentDao paymentDao;
    @Autowired
    private TransactionTemplate transactoinTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RewardDao rewardDao;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    private RedisSyncLocker redisSyncLocker;
    @Autowired
    private AccountBalanceDao accountBalanceDao;
    @Autowired
    private StorePayDao storePayDao;
    @Value("${api.gateway.url}")
    private String baseURL;

    public static final String tradeUrl = "https://qrcode.jlpay.com/api/pay/micropay";
    public static final String queryUrl = "https://qrcode.jlpay.com/api/pay/chnquery";
    private static final String sysPriKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCky3bZM0w796ALxwFwAQd7YegV5hEQ6shPCbsqZGEwkAn6gikYtfHW7hrlRBr+SVRW9lDvaUTX1NmSEqFsELj684WefBFpYznaBzZgr23mALM6BvGH66rgIeu+KCIAuTFErPf+DNIVRCCPQ5SnnNZvrcUBM9sidDj1WUbCqFRavjX2L8+30RG1IW78Mec5yxrjlCH0Z7VjBNsz+KoB9sYKxEyyiQtkTM4mXRtFQxzGcomREXzEyW39UKM3oQvR+jfL2Rqcc1mB2VrAgT6ZXMccik0en4kT9KWZgDrtrNvOE5uGgjzoJFmByBY8PeXC4KAQ5lR90lJoznBT9Hpy87L3AgMBAAECggEBAJOVM8aozikWRtrFSmBIS68Pq42REM+Zs/I0wM3iP7gCBy21y6A5sW/OpX+VUqdQfJu01B7Uo7a3BHJxBOeGwmLcHFomumErX/AGbYiBE2bcUaYx+bTENa+sMTeHMYx8Tcc3MJDwYmRxMseaulKxfsldUgUVr7ZXZ3syjNBfd8wbBMsjsQ8QQsLaB4Srh7GsMiGOtlFHUVZp1P/U9WH3cfIa+N/RUyvn8di9kOYFOXhCMeacsvS9plWisiU64WY2XsW7BH3jI+kYdjUqkSkj+8pc305TQgpfACpXmv9AnhIH1OcHx1vIvPf7kI+8pvm5GJc7fwfDQ9rOhEvGU0+4yMECgYEAzlSud8KcZUtAIihI9wQsWf8c3n8nAOGQ5Co6Xba8H53RBDZhEFdPVOZP/NUKtEFmdDjfNKFbHzIcw+FQ8IqSD72C3kHPHYxs8D+XtDwRnz3TE6+RaxJ695HBpNeJR07FlGFaSEK3D4+fbkW9/BKI5ZfiaUR1CV3ZVnIuaavKj98CgYEAzHcW5gRPIfU+TL8HralLVxYL7hb/MpZyA3P8s2Agg83P57G58l/MKSXiH1AA/7EMzoYJK3d4ctMwWVykRuRGIWiDPUZaLma9fs4GUWI+WHeVYycyeaXWzQcZlYQFnibAvyVzH9jO1PFw78uXmBQsltynobkZ9X9agc3Emp4tX+kCgYBxqqUSxNtz0ijaqGbJ7jqgubIlwNaz3Y/8ombVCb5JjJ+BOpPudKr3komuN49WDlFq5YnRbLLOVMUUBCSa3zvn//cAijCXjqzVDbN9TzpGB8EoryflXKDxkhKjxTmTVwnx3E/oTxiaMf0ausEXBP71vN62L0hqiJEa1nxLKqDE8QKBgQCn4Cuz5dvXJNXnC33Rb0vFj/txm/4iWfX4sdXMrWNk9Kn8MSdcQp2NN2aGkRiQ15yNQO3se2Yw2Qc8h9z1u9189qOyvr2ylXaG07/KOGC6IE1OoNNHoAtSQb8WzNQT+vuMtcHlZwzDOA2jRUUNf5rwrvEPzrvqnosAQqNm0/KraQKBgD7MAuoOok+S7wkffT8WxjY8u/duf4xwTQxVzgiAGjlHPneMmQei7Te0MxnH7/LojqfroD2FKC9pJD9p/KSfKTl+4xjS0fP3G5tyfonqzCbieguq0b+tvf7ed17OkETbKrMWvqFkfytySB7ekylNqnzpbGHfMfyftihDe0UD4lXv";
    //嘉联公钥
    private static final String jlPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApMt22TNMO/egC8cBcAEHe2HoFeYREOrITwm7KmRhMJAJ+oIpGLXx1u4a5UQa/klUVvZQ72lE19TZkhKhbBC4+vOFnnwRaWM52gc2YK9t5gCzOgbxh+uq4CHrvigiALkxRKz3/gzSFUQgj0OUp5zWb63FATPbInQ49VlGwqhUWr419i/Pt9ERtSFu/DHnOcsa45Qh9Ge1YwTbM/iqAfbGCsRMsokLZEzOJl0bRUMcxnKJkRF8xMlt/VCjN6EL0fo3y9kanHNZgdlawIE+mVzHHIpNHp+JE/SlmYA67azbzhObhoI86CRZgcgWPD3lwuCgEOZUfdJSaM5wU/R6cvOy9wIDAQAB";


    @Autowired
    private PaymentServiceImpl service;

    public AllPayBaseResult jlPay(Order order, String authCode, StorePay storePay, Store store) throws Exception {
        AllPayBaseResult payResult = JLMicropay(store.getName(), order, authCode, storePay.getMchId());
        log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{},订单内容{}", order.getStoreId(), order.getId(), "支付开始", payResult, order);
        log.info("payResult" + payResult);
        order.setPayChannel(OrderPayChannel.JL);
        if (payResult.isSuccess()) {
            // 支付成功，更新订单状态
            Payment payment = service.createPaymentBySwiftPassResult(payResult, storePay.getStoreId());
            // TODO: 2018/8/23  订单状态不应该区分是否履行。该平台可以不管理订单履行情况，因为一般都是线下履行
            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(payResult.getTradeType());
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付成功", payResult);
            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    orderDao.save(order);
                    paymentDao.save(payment);
                }
            });
            service.postPaymentSuccess(order, store);
        } else if (payResult.isFailed()) {
            // 支付失败，允许订单再次支付
            order.setStatus(OrderStatus.CANCELED);
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付失败", payResult);
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    orderDao.save(order);
                }
            });
        } else {
            // 支付结果不确定
            order.setStatus(OrderStatus.NOTSURE);
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    orderDao.save(order);
                }
            });
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付结果不确定", payResult);
            aliyunMNSSend.sendClint(order.getId());
        }
        redisTemplate.opsForValue().set(order.getId(), order.getId(), 5, TimeUnit.SECONDS);
        return payResult;
    }

    public ALLPayQrCodeResult JLQRCode(Order order, StorePay storePay) {
        QrcodePayRequest request = new QrcodePayRequest(order.getId(), String.valueOf((int) Math.rint(order.getAmount() * 100)), service.getBody(order));
        order.setPayChannel(OrderPayChannel.JL);
        request.setMchId(storePay.getMchId());
        request.setNotifyUrl(baseURL + "/v1/pay/callBack");
        ALLPayQrCodeResult result = new ALLPayQrCodeResult();
        QrcodePayResponse response = TransExecuteService.executor(request, QrcodePayResponse.class);
        if (response.getStatus() == "1") {
            result.setCodeImgURL(response.getCodeUrl());
            result.setStatus("0");
            result.setResultCode("0");
            // 更新订单状态到支付中，防止其被更新
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    order.setStatus(OrderStatus.NOTSURE);
                    orderDao.save(order);
                }
            });
        }
        return result;
    }

    public ALLPayQrCodeResult JLRewardQRCode(Reward reward) {
        QrcodePayRequest request = new QrcodePayRequest(reward.getId(), String.valueOf((int) Math.rint(reward.getTotal() * 100)), service.getRewardBody(reward));
        StorePay storePay = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
        reward.setPayChannel(OrderPayChannel.JL);
        request.setMchId(storePay.getMchId());
        request.setNotifyUrl(baseURL + "/v1/pay/callBack");
        ALLPayQrCodeResult result = new ALLPayQrCodeResult();
        QrcodePayResponse response = TransExecuteService.executor(request, QrcodePayResponse.class);
        if (response.getStatus() == "1") {
            result.setCodeImgURL(response.getCodeUrl());
            result.setStatus("0");
            result.setResultCode("0");
            // 更新订单状态到支付中，防止其被更新
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    reward.setStatus(OrderStatus.NOTSURE);
                    rewardDao.save(reward);
                }
            });
        }
        result.setErrMsg(response.getRetMsg());
        return result;
    }


    private AllPayBaseResult JLMicropay(String storeName, Order order, String authCode, String mchId) {
        //初始化请求实体
        order.setPayChannel(OrderPayChannel.JL);
        JLMicroPayAsynRequest request = new JLMicroPayAsynRequest(order.getId(), String.valueOf((int) Math.rint(order.getAmount() * 100)), service.getBody(order), authCode);
        request.setMchId(mchId);
        request.setBody(storeName);
        request.setMchCreateIp("222.209.78.84");
        Map map = micsort(request);
        MicropayResponse response = executor(map, MicropayResponse.class);
        System.out.println("嘉联支付后的返回结果" + response);
        AllPayBaseResult result = new AllPayBaseResult();
        switch (response.getStatus()) {
            case "1":
                result.setNeedQuery("Y");
                break;
            case "2":
                result.setStatus("0");
                result.setResultCode("0");
                break;
            case "3":
                result.setNeedQuery("N");
                break;
        }
        result.setMchId(response.getMchId());
        result.setOutTradeNo(response.getOutTradeNo());
        result.setStatus(response.getStatus());
        result.setTotalFee(Integer.valueOf(response.getTotalFee()));
        result.setTimeEnd(response.getOrderTime());
        System.out.println("支付后的返回结果" + result);
        result.setErrMsg(response.getRetMsg());
        return result;
    }


    public AllPayJsPayResult jlJsPay(String mchId, String openId, Order order) {
        order.setPayChannel(OrderPayChannel.JL);
        OfficialAccPayRequest request = new OfficialAccPayRequest(order.getId(), String.valueOf((int) Math.rint(order.getAmount() * 100)), service.getBody(order), "");
        request.setMchId(mchId);
        request.setOpenId(openId);
        request.setMchCreateIp("172.18.0.1");
        request.setNotifyUrl(baseURL + "/v1/pay/callBack");
        AllPayJsPayResult result = new AllPayJsPayResult();
        OfficialAccPayResponse response = new OfficialAccPayResponse()/*=executor(request, OfficialAccPayResponse.class)*/;
        switch (response.getStatus()) {
            case "1":
                result.setStatus("0");
                result.setResultCode("0");
                result.setPayInfo(response.getPayInfo());
                break;
            case "3":
                result.setErrMsg(response.getRetMsg());
                break;
        }

        return result;
    }


    public AllPayReverseResult jlCancelPay(String orderId) {
        AllPayReverseResult result = new AllPayReverseResult();
        Order order = orderDao.findOne(orderId);

        Reward reward = rewardDao.findOne(orderId);
        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.JL);
            if (reward.getStatus().equals(OrderStatus.CANCELED)) {
                throw new RuntimeException("该笔支付已经被取消");
            } else if (reward.getStatus().equals(OrderStatus.UNFINISHED) || reward.getStatus().equals(OrderStatus.FINISHED)) {
                throw new RuntimeException("已经成功支付，取消支付操作被中止。");
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
                AllPayBaseQueryResult paymentResult = jlQueryPay(reward.getId(), store.getMchId());
                if (paymentResult.isSuccess()) {
                    throw new RuntimeException("已经成功支付，取消支付操作被中止。");
                }
                CancelRequest request = new CancelRequest(UuidUtil.getUuid(), String.valueOf((int) Math.rint(order.getAmount() * 100)), order.getId());
                request.setMchId(store.getMchId());
                CancelResponse response = new CancelResponse()/*=executor(request, CancelResponse.class)*/;
                switch (response.getStatus()) {
                    case "1":
                        result.setStatus("0");
                        result.setResultCode("0");
                        break;
                    case "3":
                        result.setErrMsg(response.getRetMsg());
                        break;
                }
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setStatus(OrderStatus.INIT);
                            rewardDao.save(reward);
                        }
                    });
                    return result;
                } else {
                    throw new RuntimeException(result.getErrMsg());
                }
            }
        } else {
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "支付已经被取消，请到订单列表查询确认");
                throw new RuntimeException("支付已经被取消，请到订单列表查询确认");
            } else if (order.getStatus().equals(OrderStatus.UNFINISHED) || order.getStatus().equals(OrderStatus.FINISHED)) {
                throw new RuntimeException("订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
                AllPayBaseQueryResult paymentResult = jlQueryPay(reward.getId(), store.getMchId());
                if (paymentResult.isSuccess()) {
                    throw new RuntimeException("订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                }
                // 先调用撤销订单接口
                order.setPayChannel(OrderPayChannel.JL);
                CancelRequest request = new CancelRequest(UuidUtil.getUuid(), String.valueOf((int) Math.rint(order.getAmount() * 100)), order.getId());
                request.setMchId(store.getMchId());
                CancelResponse response = new CancelResponse()/* =executor(request, CancelResponse.class)*/;
                switch (response.getStatus()) {
                    case "1":
                        result.setStatus("0");
                        result.setResultCode("0");
                        break;
                    case "3":
                        result.setErrMsg(response.getRetMsg());
                        break;
                }
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setStatus(OrderStatus.CANCELED);
                            orderDao.save(order);
                        }
                    });
                    return result;
                } else {
                    throw new RuntimeException("取消支付失败，请稍后再试");
                }
            }
        }


    }


    public AllPayRefundQueryResult JlQueryRefundResult(String refundOrderId) {
        AllPayRefundQueryResult result = new AllPayRefundQueryResult();
        OrderChnQueryRequest request = new OrderChnQueryRequest();
        request.setOutTradeNo(refundOrderId);
        OrderChnQueryResponse response = new OrderChnQueryResponse();
        switch (response.getStatus()) {
            case "2":
                result.setRefundStatus("SUCCESS");
                result.setStatus("0");
                result.setResultCode("0");
                result.setRefundId(response.getOutTradeNo());
                result.setRefundTime(response.getTransTime());
                break;
        }

        return result;
    }

    public void JlcallbackForThirdPartyRefundSuccess(AllPayRefundQueryResult result) {
        log.debug("Step in callback for third party refund success...");
        Payment payment = paymentDao.findOne(result.getRefundId());
        payment.setStatus(PaymentStatus.SUCCESS);
        payment.setSuccess(true);

        Date paymentTime = MyDateUtils.getDateFormatDd(result.getRefundTime(), "yyyyMMddHHmmss");
        payment.setCreateTime(paymentTime);

        Order refundOrder = orderDao.findOne(payment.getOrderId());
        refundOrder.setPayChannel(OrderPayChannel.JL);
        refundOrder.setStatus(OrderStatus.REFUNDED);
        refundOrder.setPaymentTime(paymentTime);

        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
                paymentDao.save(payment);
            }
        });

        try {
            service.postRefundSuccess(refundOrder);
        } catch (Exception e1) {
            log.info(e1.toString());
        }
    }

    public void JlcallbackForThirdPartyRefundFail(AllPayRefundQueryResult result) {
        Order refundOrder = orderDao.findOne(result.getOutRefundNo());
        refundOrder.setPayChannel(OrderPayChannel.JL);
        refundOrder.setStatus(OrderStatus.INIT);

        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
            }
        });
    }


    public AllPayBaseQueryResult jlQueryPay(String orderId, String mchId) {
        OrderChnQueryRequest request = new OrderChnQueryRequest();
        request.setOutTradeNo(orderId);
        request.setMchId(mchId);
        AllPayBaseQueryResult result = new AllPayBaseQueryResult();
        Map map = querySort(request);
        OrderChnQueryResponse response = queryExecutor(map, OrderChnQueryResponse.class);
        //  log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "进入嘉联，支付轮训中", result);
        switch (response.getStatus()) {
            case "2":
                result.setTradeState("SUCCESS");
                result.setTradeType(response.getPayType());
                result.setTimeEnd(response.getTransTime());
                result.setTotalFee(Integer.valueOf(response.getTotalFee()));
                result.setOutTradeNo(response.getOutTradeNo());
                break;
            case "3":
                result.setTradeState("PAYERROR");
                break;
            case "4":
                result.setTradeState("REVERSE");
                break;
            case "5":
                result.setTradeState("REVOKED");
                break;
        }
        return result;
    }


    public void callbackForMicroPaymentSuccess(AllPayBaseQueryResult queryResult) throws Exception {
        Order order = orderDao.findOne(queryResult.getOutTradeNo());
        Reward reward = rewardDao.findOne(queryResult.getOutTradeNo());
        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.JL);
            if (reward.getStatus().equals(OrderStatus.FINISHED) || reward.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return;
            }
            reward.setPaymentTime(MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss"));
            reward.setChannel(queryResult.getTradeType());
            reward.setStatus(OrderStatus.FINISHED);
            AccountBalance accountBalance = accountBalanceDao.findByStoreId(reward.getStoreId());
            log.info("accountBalance" + accountBalance);
            if (accountBalance == null) {
                accountBalance = new AccountBalance(queryResult.getTotalFee() / 100.0, reward.getStoreId());
            } else {
                accountBalance.setAmount(accountBalance.getAmount() + queryResult.getTotalFee() / 100.0);
            }
            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    rewardDao.save(reward);

                }
            });
            accountBalanceDao.save(accountBalance);
            aliyunMNSSend.sendClint(reward.getId());
        } else {
            if (order.getStatus().equals(OrderStatus.FINISHED) || order.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return;
            }
            order.setPayChannel(OrderPayChannel.JL);
            Store store = storeDao.findOne(order.getStoreId());

            Payment payment = new Payment();
            payment.setId(queryResult.getTransactionId());
            payment.setOrderId(queryResult.getOutTradeNo());
            payment.setStoreId(order.getStoreId());
            payment.setSuccess(queryResult.isSuccess());
            payment.setStatus(PaymentStatus.SUCCESS);
            Date paymentTime = MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss");
            payment.setCreateTime(paymentTime);
            payment.setAmount(queryResult.getTotalFee() / 100.0);
            payment.setChannel(queryResult.getTradeType());


            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(queryResult.getTradeType());

            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    paymentDao.save(payment);
                    orderDao.save(order);
                }
            });

            service.postPaymentSuccess(order, store);
        }
    }


    public void callbackForMicroPaymentFailed(String orderId, AllPayBaseQueryResult queryResult) throws Exception {
        Order order = orderDao.findOne(orderId);
        Reward reward = rewardDao.findOne(orderId);


        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.JL);
            if (reward.getStatus().equals(OrderStatus.INIT)) {
                // 说明已经处理过支付失败的情况
                return;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                reward.setStatus(OrderStatus.INIT);
                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        rewardDao.save(reward);
                    }
                });
            }
        } else {
            order.setPayChannel(OrderPayChannel.JL);
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                // 说明已经处理过支付失败的情况
                return;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                order.setStatus(OrderStatus.CANCELED);

                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        orderDao.save(order);
                    }
                });
            }
        }
    }

    public <T extends TransBaseResponse> T executor(Map map, Class<? extends TransBaseResponse> clazz) {
        String signDate = RSA256Utils.sign256(JSON.toJSONString(map), sysPriKey);
        System.out.println("签名:" + signDate);
        map.put("sign", signDate);
        String signContext = getSignJSONContext(map, "sign");
        boolean doCheck = RSA256Utils.verify256(signContext, jlPubKey, map.get("sign").toString());
        log.info("订单号{} 验签{}", map, doCheck);
        String responseStr = CommonService.httpToInvoke(JSON.toJSONString(map), tradeUrl);
        System.out.println("嘉联支付返回内容" + responseStr);
        return (T) JSON.parseObject(responseStr, clazz);
    }

    public <T extends TransBaseResponse> T queryExecutor(Map map, Class<? extends TransBaseResponse> clazz) {
        String signDate = RSA256Utils.sign256(JSON.toJSONString(map), sysPriKey);
        System.out.println("签名:" + signDate);
        map.put("sign", signDate);
        String signContext = getSignJSONContext(map, "sign");
        boolean doCheck = RSA256Utils.verify256(signContext, jlPubKey, map.get("sign").toString());
        log.info("订单号{} 验签{}", map, doCheck);
        String responseStr = CommonService.httpToInvoke(JSON.toJSONString(map), queryUrl);
        System.out.println("嘉联支付返回内容" + responseStr);
        return (T) JSON.parseObject(responseStr, clazz);
    }

    public Map micsort(JLMicroPayAsynRequest request) {
        Map<String, Object> jsonObject = new TreeMap<String, Object>();
        jsonObject.put("mch_id", request.getMchId());
        jsonObject.put("nonce_str", request.getNonceStr());
        jsonObject.put("out_trade_no", request.getOutTradeNo());
        jsonObject.put("body", request.getBody());
        jsonObject.put("attach", request.getAttach());
        jsonObject.put("total_fee", request.getTotalFee());
        jsonObject.put("auth_code", request.getAuthCode());
        jsonObject.put("mch_create_ip", request.getMchCreateIp());
        jsonObject.put("org_code", request.getOrgCode());
        return jsonObject;
    }

    public Map querySort(OrderChnQueryRequest request) {
        Map<String, Object> jsonObject = new TreeMap<String, Object>();
        jsonObject.put("org_code", request.getOrgCode());
        jsonObject.put("mch_id", request.getMchId());
        jsonObject.put("nonce_str", request.getNonceStr());
        jsonObject.put("out_trade_no", request.getOutTradeNo());
        return jsonObject;
    }

    public String getSignJSONContext(Map<String, Object> contextMap, String... ignoresKeys) {
        List<String> ignoresKeyList = null;
        if (ignoresKeys != null) {
            ignoresKeyList = Arrays.asList(ignoresKeys);
        } else {
            ignoresKeyList = new ArrayList<String>();
        }
        List<String> keys = new ArrayList<String>(contextMap.keySet());
        Collections.sort(keys);
        Map<String, Object> treeMap = new TreeMap<String, Object>();
        for (String key : keys) {
            if (!ignoresKeyList.contains(key)) {
                treeMap.put(key, contextMap.get(key));
            }
        }
        return JSON.toJSONString(treeMap);
    }

}
